package com.bosssoft.boss_exam_web.Controller;


import com.bosssoft.boss_exam_core.exception.BusinessException;
import com.bosssoft.boss_exam_core.exception.QueryDataException;
import com.bosssoft.boss_exam_core.storage.StorageService;
import com.bosssoft.boss_exam_core.util.common.CharUtil;
import com.bosssoft.boss_exam_core.util.web.ResponseUtil;
import com.bosssoft.boss_exam_db.entity.Filemetadata;
import com.bosssoft.boss_exam_db.service.busines.FilemetadataService;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 文件存储表 前端控制器
 * </p>
 *
 * @author cherish
 * @since 2018-11-11
 */
@RestController
@RequestMapping("/admin/filemetadata")
@Api(value="对象存储元数据控制器")
@Slf4j
public class FilemetadataController {

//    注入对象存储元数据服务
    @Autowired
    private FilemetadataService filemetadataService;

//注入文件存储服务
    @Autowired
    private StorageService storageService;

    @Autowired
    @Qualifier("transactionManager")
    private PlatformTransactionManager transactionManager;
    /***
     * @Author lys(cherish)
     * @Phone 17720799636
     * @Date  2019/4/7
     * @Description 为文件名称生成随机KEY
     * @Param [originalFilename] 原来文件名
     * @Return java.lang.String
     * @Exception
     * @since JDK 1.8
     **/
    private String generateKey(String originalFilename){
        int index = originalFilename.lastIndexOf('.');
        String suffix = originalFilename.substring(index);

        String key = null;
        Filemetadata filemetadata = null;

        do{
            key = CharUtil.getRandomString(20) + suffix;
            filemetadata = filemetadataService.findByKey(key);
        }
        while(filemetadata != null);

        return key;
    }

    @ApiOperation(value = "对象存储元数据查询", notes = "根据对象存储元数据的KEY、name查询", httpMethod = "GET", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "key", value = "元数据键", dataType = "String", required = false, dataTypeClass = String.class),
            @ApiImplicitParam(name = "name", value = "元数据名称", dataType = "String", required = false, dataTypeClass = String.class),
            @ApiImplicitParam(name = "page", value = "当前页码", dataType = "String", required = false, dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "limit", value = "每页显示条数", dataType = "String", required = false, dataTypeClass = Integer.class),
            @ApiImplicitParam(name = "sort", value = "排序依据", dataType = "String", required = false, dataTypeClass = String.class),
            @ApiImplicitParam(name = "order", value = "排序方式", dataType = "String", required = false, dataTypeClass = String.class)
    })
    @GetMapping("/list")
    public Object list(String key, String name,
                       @RequestParam(value = "page", defaultValue = "1") Integer page,
                       @RequestParam(value = "limit", defaultValue = "10") Integer limit,
                       String sort, String order){
        PageInfo<Filemetadata> filemetadataPageInfo = filemetadataService.querySelective(key, name, page, limit, sort, order);
        if (filemetadataPageInfo == null) {
            throw new QueryDataException();
        } else {
            Map<String, Object> data = new HashMap<>();
            data.put("total", filemetadataPageInfo.getTotal());
            data.put("items", filemetadataPageInfo.getList());
            return ResponseUtil.ok(data);
        }
    }

    @ApiOperation(value = "上传文件", notes = "上传MultipartFile文件", httpMethod = "POST", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "文件对象", dataType = "MultipartFile", required = true, dataTypeClass = MultipartFile.class),
    })
    @PostMapping("/create")
    public Object create(@RequestParam("file") MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseUtil.badArgumentValue();
        }
        String key = generateKey(originalFilename);
        String url = storageService.store(file.getInputStream(), file.getSize(), file.getContentType(), originalFilename);
        Map<String, Object> data = new HashMap<>();
        data.put("urlLys", url);
        return ResponseUtil.ok(data);
    }

    @ApiOperation(value = "对象存储元数据查询", notes = "根据对象存储元数据KEY查询元数据信息", httpMethod = "POST", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "对象存储元数据KEY", dataType = "String", required = true, dataTypeClass = String.class),
    })
    @PostMapping("/read")
    public Object read(String id) {
        if(id == null){
            return ResponseUtil.badArgument();
        }
        Filemetadata filemetadata = null;
        try {
            filemetadata = filemetadataService.selectByKey(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(filemetadata == null){
            return ResponseUtil.badArgumentValue();
        }
        return ResponseUtil.ok(filemetadata);
    }

    @ApiOperation(value = "对象存储元数据信息更新", notes = "更新元数据", httpMethod = "POST", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "filemetadata", value = "对象存储元数据信息", dataType = "Filemetadata", required = true, dataTypeClass = Filemetadata.class),
    })
    @PostMapping("/update")
    public Object update(@RequestBody Filemetadata filemetadata) {
        int i = filemetadataService.updateNotNull(filemetadata);
        return ResponseUtil.ok(filemetadata);
    }

    @ApiOperation(value = "对象存储元数据删除", notes = "删除元数据，实则根据KEY查询并删除", httpMethod = "POST", response = Object.class)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "filemetadata", value = "对象存储元数据信息", dataType = "filemetadata", required = true, dataTypeClass = Filemetadata.class),
    })
    @PostMapping("/delete")
    public Object delete(@RequestBody Filemetadata filemetadata) {
//       引入编程事务
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
//       设置事务传播行为：required 如有事务加入事务，无事务新建一起事务
//       作用将多个service操作都使用同一个connection事务
        defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus status = transactionManager.getTransaction(defaultTransactionDefinition);
        try {
            filemetadataService.updateByKey(filemetadata,filemetadata.getImgKey());
            storageService.delete(filemetadata.getImgKey());
            // 事务提交
            transactionManager.commit(status);
            return ResponseUtil.ok();
        }catch (Exception e){
            transactionManager.rollback(status);
            throw new BusinessException("删除对象存储失败");
        }
    }

}
